package com.ccp.dev.form.util;

import com.ccp.dev.core.basic.engine.GroovyScriptEngine;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.*;
import com.ccp.dev.form.consts.FormConstants;
import com.ccp.dev.form.model.FormDef;
import com.ccp.dev.form.model.FormField;
import com.ccp.dev.form.model.FormRights;
import com.ccp.dev.form.model.FormTable;
import com.ccp.dev.form.service.FormTableService;
import com.ccp.dev.form.service.ParseReult;
import com.ccp.dev.workflow.dataKey.KeyGenerator;
import com.ccp.dev.workflow.dataKey.impl.GuidGenerator;
import com.ccp.dev.workflow.dataKey.impl.IdentityGenerator;
import com.ccp.dev.workflow.dataKey.impl.TimeGenerator;
import net.sf.json.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 表单实用函数。
 *
 * @author ray。
 */
public class FormUtil {
    private FormUtil() {
    }

    ;
    protected static Map<String, Short> controlTypeMap = new HashMap<>();

    static {
        controlTypeMap.put("textinput", FieldPool.TEXT_INPUT);
        controlTypeMap.put("textarea", FieldPool.TEXTAREA);
        controlTypeMap.put("dictionary", FieldPool.DICTIONARY);
        controlTypeMap.put("user", FieldPool.SELECTOR_USER_SINGLE);
        controlTypeMap.put("rolepicker", FieldPool.SELECTOR_ROLE_MULTI);
        controlTypeMap.put("departmentpickerMulti", FieldPool.SELECTOR_ORG_MULTI);
        controlTypeMap.put("positionpicker", FieldPool.SELECTOR_POSITION_SINGLE);
        controlTypeMap.put("userMulti", FieldPool.SELECTOR_USER_MULTI);
        controlTypeMap.put("attachement", FieldPool.ATTACHEMENT);
        controlTypeMap.put("ckeditor", FieldPool.CKEDITOR);
        controlTypeMap.put("selectinput", FieldPool.SELECT_INPUT);
        controlTypeMap.put("officecontrol", FieldPool.OFFICE_CONTROL);
        controlTypeMap.put("checkbox", FieldPool.CHECKBOX);
        controlTypeMap.put("radioinput", FieldPool.RADIO_INPUT);
        controlTypeMap.put("datepicker", FieldPool.DATEPICKER);
        controlTypeMap.put("hidedomain", FieldPool.HIDEDOMAIN);
        controlTypeMap.put("rolepickerMulti", FieldPool.SELECTOR_ROLE_SINGLE);
        controlTypeMap.put("departmentpicker", FieldPool.SELECTOR_ORG_SINGLE);
        controlTypeMap.put("positionpickerMulti", FieldPool.SELECTOR_POSITION_MULTI);
        controlTypeMap.put("websigncontrol", FieldPool.WEBSIGN_CONTROL);
        controlTypeMap.put("pictureshowcontrol", FieldPool.PICTURE_SHOW_CONTROL);
        controlTypeMap.put("processinstance", FieldPool.SELECTOR_PROCESS_INSTANCE);
    }

    private static Log logger = LogFactory.getLog(FormUtil.class);
    /**
     *正则表达式,不必每次都产生正则表达式实例。
     */
    private final static Pattern REGEX = Pattern.compile("\\[(.*?)\\]", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);

    /**
     * 获取意见表单字段。
     *
     * <pre>
     * 通过解析表单，返回表单中的意见字段数据。
     * </pre>
     *
     * @param html
     * @return
     */
    public static Map<String, String> parseOpinion(String html) {
        Map<String, String> map = new HashMap<>(16);
        Document doc = Jsoup.parseBodyFragment(html);
        Elements list = doc.select("[name^=opinion:]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            String memo = el.attr("opinionname");
            String opinionName = name.replaceFirst("^opinion:", "");
            map.put(opinionName, memo);
        }
        return map;
    }

    /**
     * 获取默认的权限数据
     *
     * @param title 字段名称
     * @param memo  字段描述
     * @param type  字段类型
     * @return JSONObject
     */
    public static JSONObject getPermissionJson(String title, String memo, int type) {
        String defJson = "{type:'everyone',id:'', fullname:''}";
        JSONObject json = new JSONObject();
        json.element("title", title);
        json.element("memo", memo);
        if (type != FormRights.TABLE_SHOW_RIGHTS) {
            json.element("read", defJson);
            json.element("write", defJson);
            if (type != FormRights.TABLE_RIGHTS) {
                json.element("required", "{type:'none',id:'', fullname:''}");
            }
        } else {
            //子表显示可写：w  子表显示只读：r  为显示  其它为隐藏（y）   可以增加默认
            json.element("show", "{addBtn:'true'}");
        }
        return json;
    }

    /**
     * 填充权限列表
     *
     * @param rightList           总权限列表
     * @param formRightsList      表单权限列表
     * @param tableRightsList     表权限列表
     * @param otherRightsList     其他权限列表
     * @param tableShowRightsList 子表显示与否权限列表
     */
    public static void fillRightsList(List<FormRights> rightList, List<FormRights> formRightsList, List<FormRights> tableRightsList, List<FormRights> otherRightsList, List<FormRights> tableShowRightsList) {
        for (FormRights bpmFormRights : rightList) {
            if (bpmFormRights.getType() == FormRights.FIELD_RIGHTS) {
                formRightsList.add(bpmFormRights);
            } else if (bpmFormRights.getType() == FormRights.TABLE_RIGHTS) {
                tableRightsList.add(bpmFormRights);
            } else if (bpmFormRights.getType() == FormRights.TABLE_SHOW_RIGHTS) {
                tableShowRightsList.add(bpmFormRights);
            } else {
                otherRightsList.add(bpmFormRights);
            }
        }
    }

    /**
     * 将脚本中的字段使用实际的值进行替换，返回实际的脚本。
     *
     * @param script
     * @param map
     * @return
     */
    private static String parseScript(String script, Map<String, Object> map) {
        if (map == null || map.size() == 0) {
            return script;
        }
        Matcher regexMatcher = REGEX.matcher(script);
        while (regexMatcher.find()) {
            String tag = regexMatcher.group(0);
            // 取得关联字段的值。
            String key = regexMatcher.group(1);
            if (map.get(key) != null) {
                String value = map.get(key).toString();
                script = script.replace(tag, value);
            }
        }
        return script;
    }

    /**
     * 计算脚本，并可根据其他字段进行运算。
     *
     * @param script
     * @param map
     * @return
     */
    public static Object calcuteField(String script, Map<String, Object> map) {
        GroovyScriptEngine engine = AppUtil.getBean(GroovyScriptEngine.class);
        script = parseScript(script, map);
        return engine.executeObject(script, null);
    }

    /**
     * 根据指定的名称，查找某个节点的父节点。
     *
     * @param node          node
     * @param containerName containerName
     * @return element
     */
    private static Element getContainer(Element node, String containerName) {
        Element parent = node;
        while ((parent = (Element) parent.parent()) != null) {
            String name = parent.attr("name");
            if (containerName.equals(name)) {
                return parent;
            }
        }
        return node;
    }

    /**
     * 处理主表字段
     *
     * @param doc doc
     */
    private static void parseMainField(Document doc) {
        Elements list = doc.select("input[name^=m:],div[name^=m:],ul[name^=m:],textarea[name^=m:],select[name^=m:],button.selectorBtn,button.uploadFileBtn,button.uploadImgBtn,a.link,a.extend");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            // 获取字段名
            String fieldName = name.replaceAll("^.*:", "").toLowerCase();
            // 处理附件的bug
            if (StringUtil.isEmpty(name)) {
                name = el.attr("field");
                // 不是子表
                if (StringUtil.isNotEmpty(name) && name.matches("m:(\\w*):(\\w*)")) {
                    fieldName = name.replaceAll("^.*:", "").toLowerCase();
                }
            }
            // 解析模版，对模版进行复制复制和授权的处理。
            parseMainField(el, fieldName);
        }
    }

    /**
     * 解析意见。
     *
     * @param doc doc
     */
    private static void parseOpinion(Document doc) {
        parseOpinion(doc, null);
    }

    /**
     * 解析意见。
     *
     * @param doc doc
     */
    private static void parseOpinion(Document doc, ParseReult result) {
        // opinion:www
        Elements list = doc.select("[name^=opinion:]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            String memo = el.attr("opinionname");
            String opinionName = name.replaceFirst("^opinion:", "");
            // getOpinion(String opinionName, String html, Map<String, Map<String, Map>> model, Map<String, Map<String, Map>> permission)
            String str = "&lt;#assign " + opinionName + "Opinion&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getOpinion('" + opinionName + "'," + opinionName + "Opinion, model, permission)}";
            el.before(str);
            el.remove();
            if (result != null) {
                result.addOpinion(opinionName, memo);
            }
        }
    }

    /**
     * 处理弹出窗口模式。
     *
     * @param doc    doc
     * @param newRow newRow
     * @param window window
     */
    private static void parseSubTableFormField(Document doc, Element newRow, Element window) {
        Elements fields = newRow.select("[fieldname^=s:]");
        for (Iterator<Element> it = fields.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("fieldname");
            // 获取字段名
            String fieldName = name.replaceAll("^.*:", "").toLowerCase();
            // <td fieldname="s:subtable:name">${table.name}</td>
            // 示例添加 ${table.name}
            el.append("${table." + fieldName + "}");
        }
        // 对form表单进行遍历，添加隐藏域。
        Elements windowFields = window.select("[name^=s:]");
        for (Iterator<Element> it = windowFields.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            // 获取字段名
            String fieldName = name.replaceAll("^.*:", "").toLowerCase();
            Element appendTag = doc.createElement("input").attr("type", "hidden").attr("name", name);
            appendTag.attr("value", "${table." + fieldName + "}");
            newRow.children().last().after(appendTag);
        }
    }

    private static Pattern PATTERN = Pattern.compile("(\\{)|(\\})");
    /**
     * @param doc         doc
     * @param parentEl    parentEL
     * @param controlName controlName
     * @param formField   formField
     * @return list
     */
    private static List<Pair> parseChilds(Document doc, Element parentEl, String controlName, FormField
            formField) {
        List<Pair> list = new ArrayList<>(16);
        Elements elList = parentEl.select("input,select,textarea");
        for (Iterator<Element> it = elList.iterator(); it.hasNext(); ) {
            Element el = it.next();
            Pair pair = new Pair(el, formField.getFieldName());
            list.add(pair);
            short controlType = formField.getControlType();
            String fieldType = formField.getFieldType();
            el.attr("name", controlName);
            // 字段的显示标识或名称 说明
            el.attr("lablename", formField.getFieldDesc());

            short isReference = formField.getIsReference();
            if (isReference == 1) {
                el.attr("linktype", String.valueOf(controlType));
                el.attr("refid", controlName + "ID");
            }

            // 验证
            String valid = handValidate(formField);
            if (StringUtil.isNotEmpty(valid)) {
                // 原来的对象 是否有 validate 这个属性
                String validate = el.attr("validate");
                if (StringUtil.isNotEmpty(validate)) {
                    // 如果有validate这个属性那么就要把两个validate对象合并成一个对象
                    Matcher m = PATTERN.matcher(valid);
                    Matcher n = PATTERN.matcher(validate);
                    valid = "{" + m.replaceAll("") + "," + n.replaceAll("") + "}";
                }
                el.attr("validate", valid);
            }
            if (BeanUtils.isNotEmpty(formField.getStyle())) {
                el.attr("style", formField.getStyle());
            }

            Map<String, String> propertyMap = formField.getPropertyMap();
            String scope = "";
            switch (controlType) {
                //文字类型
                case FieldPool.TEXT_INPUT:
                    el.wrap("<span></span>");
                    if ("varchar".equals(fieldType)) {
                        if ((short) 1 != formField.getIsDateString()) {
                            break;
                        }
                    } else if ("number".equals(fieldType)) {
                        Short isShowComdify = formField.getIsShowComdify();
                        String coinValue = formField.getCoinValue();
                        Integer decimalLen = formField.getDecimalLen();
                        el.attr("showtype", "{\"coinValue\":\"" + coinValue + "\",\"isShowComdify\":\"" + isShowComdify + "\",\"decimalValue\":" + decimalLen + "}");
                        break;
                    } else if (!"date".equals(fieldType)) {
                        break;
                    }
                    el.addClass("Wdate");
                    String dateformat = "yyyy-MM-dd";
                    if (propertyMap.containsKey("format")) {
                        dateformat = propertyMap.get("format");
                    }
                    if (propertyMap.containsKey("displayDate")) {
                        el.attr("displayDate", propertyMap.get("displayDate"));
                    }
                    el.attr("dateFmt", dateformat);
                    break;
                // 数据字典。
                case FieldPool.DICTIONARY:
                    el.attr("class", "dicComboTree");
                    el.attr("nodeKey", formField.getDictType());
                    el.wrap("<span></span>");
                    break;

                // 单选用户
                case FieldPool.SELECTOR_USER_SINGLE:
                    if (propertyMap.containsKey("showCurUser")) {
                        el.attr("showCurUser", propertyMap.get("showCurUser"));
                    }
                    // 角色选择
                case FieldPool.SELECTOR_ROLE_MULTI:
                    // 部门
                case FieldPool.SELECTOR_ORG_SINGLE:
                    if (propertyMap.containsKey("showCurOrg")) {
                        el.attr("showCurOrg", propertyMap.get("showCurOrg"));
                    }
                    // 岗位
                case FieldPool.SELECTOR_POSITION_MULTI:
                    el.wrap("<span></span>");
                    Element elInput = doc.createElement("input").attr("name", controlName + "ID").attr("type", "hidden").attr("class", "hidden");

                    el.before(elInput);

                    Pair pairSelect = new Pair(elInput, formField.getFieldName() + "ID");
                    list.add(pairSelect);
                    el.attr("readonly", "readonly");
                    Elements links = parentEl.select("a.link");
                    if (links.size() > 0) {
                        Element link = links.get(0);
                        link.attr("name", controlName);
                        el.after(link);
                        Pair pLink = new Pair(link, formField.getFieldName());
                        list.add(pLink);
                    }
                    //处理组织树限定范围
                    scope = propertyMap.get("scope");
                    if (StringUtil.isNotEmpty(scope)) {
                        el.attr("scope", scope.replaceAll("'", "\""));
                    }
                    break;
                //多选用户
                case FieldPool.SELECTOR_USER_MULTI:
                    el.wrap("<span></span>");
                    Element elUsers = doc.createElement("input").attr("name", controlName + "ID").attr("type", "hidden").attr("class", "hidden");

                    Pair pairUsers = new Pair(elUsers, formField.getFieldName() + "ID");
                    list.add(pairUsers);

                    el.before(elUsers);
                    el.attr("readonly", "readonly");
                    Elements linkUsers = parentEl.select("a.link");
                    if (linkUsers.size() > 0) {
                        Element link = linkUsers.get(0);
                        link.attr("name", controlName);
                        link.removeClass("user");
                        link.addClass("users");
                        el.after(link);
                        Pair pLink = new Pair(link, formField.getFieldName());
                        list.add(pLink);
                    }
                    //处理组织树限定范围
                    scope = propertyMap.get("scope");
                    if (StringUtil.isNotEmpty(scope)) {
                        el.attr("scope", scope.replaceAll("'", "\""));
                    }
                    break;
                //单选角色
                case FieldPool.SELECTOR_ROLE_SINGLE:
                    el.wrap("<span></span>");
                    Element elRoles = doc.createElement("input")
                            .attr("name", controlName + "ID")
                            .attr("type", "hidden")
                            .attr("class", "hidden");

                    Pair pairRoles = new Pair(elRoles, formField.getFieldName() + "ID");
                    list.add(pairRoles);

                    el.before(elRoles);
                    el.attr("readonly", "readonly");
                    Elements linkRoles = parentEl.select("a.link");
                    if (linkRoles.size() > 0) {
                        Element link = linkRoles.get(0);
                        link.attr("name", controlName);
                        link.removeClass("role");
                        link.addClass("roles");
                        el.after(link);
                        Pair pLink = new Pair(link, formField.getFieldName());
                        list.add(pLink);
                    }
                    break;
                //多选组织
                case FieldPool.SELECTOR_ORG_MULTI:
                    el.wrap("<span></span>");
                    Element elOrgs = doc.createElement("input").attr("name", controlName + "ID").attr("type", "hidden").attr("class", "hidden");

                    Pair pairOrgs = new Pair(elOrgs, formField.getFieldName() + "ID");
                    list.add(pairOrgs);

                    el.before(elOrgs);
                    el.attr("readonly", "readonly");
                    Elements linkOrgs = parentEl.select("a.link");
                    if (linkOrgs.size() > 0) {
                        Element link = linkOrgs.get(0);
                        link.attr("name", controlName);
                        link.removeClass("org");
                        link.addClass("orgs");
                        el.after(link);
                        Pair pLink = new Pair(link, formField.getFieldName());
                        list.add(pLink);
                    }
                    //处理组织树限定范围
                    scope = propertyMap.get("scope");
                    if (StringUtil.isNotEmpty(scope)) {
                        el.attr("scope", scope.replaceAll("'", "\""));
                    }
                    break;
                //单选岗位
                case FieldPool.SELECTOR_POSITION_SINGLE:
                    el.wrap("<span></span>");
                    Element elPositions = doc.createElement("input")
                            .attr("name", controlName + "ID")
                            .attr("type", "hidden")
                            .attr("class", "hidden");

                    if (propertyMap.containsKey("showCurPos")) {
                        el.attr("showCurPos", propertyMap.get("showCurPos"));
                    }

                    Pair pairPositions = new Pair(elPositions, formField.getFieldName() + "ID");
                    list.add(pairPositions);

                    el.before(elPositions);
                    el.attr("readonly", "readonly");
                    Elements linkPositions = parentEl.select("a.link");
                    if (linkPositions.size() > 0) {
                        Element link = linkPositions.get(0);
                        link.attr("name", controlName);
                        link.removeClass("position");
                        link.addClass("positions");
                        el.after(link);
                        Pair pLink = new Pair(link, formField.getFieldName());
                        list.add(pLink);
                    }
                    //处理组织树限定范围
                    scope = propertyMap.get("scope");
                    if (StringUtil.isNotEmpty(scope)) {
                        el.attr("scope", scope.replaceAll("'", "\""));
                    }
                    break;
                //附件
                case FieldPool.ATTACHEMENT:
                    el.tagName("textarea");
                    el.removeAttr("type");
                    el.wrap("<div name='div_attachment_container' ></div>");
                    el.before("<div  class='attachement' ></div>");
                    el.attr("controltype", "attachment");
                    el.attr("style", "display:none;");
                    el.attr("validatable", "true");

                    Elements linkFile = parentEl.select("a.attachement");
                    if (linkFile.size() > 0) {
                        Element link = linkFile.get(0);
                        link.attr("field", controlName);
                        String ctlProperty = formField.getCtlProperty();
                        JSONObject jsonObj = null;
                        if (StringUtil.isNotEmpty(ctlProperty)) {
                            jsonObj = JSONObject.fromObject(ctlProperty);
                            if (jsonObj.has("directUpLoad")) {
                                if ("1".equals(jsonObj.get("directUpLoad").toString())) {
                                    link.attr("onclick", "AttachMent.directUpLoadFile(this);");
                                } else {
                                    link.attr("onclick", "AttachMent.addFile(this);");
                                }
                            } else {
                                link.attr("onclick", "AttachMent.addFile(this);");
                            }
                        } else {
                            link.attr("onclick", "AttachMent.addFile(this);");
                        }
                        link.removeClass("attachement").addClass("selectFile");
                        el.after(link);
                    } else {
                        el.after("<a href='#' field='" + controlName + "' validate='" + valid + "' class='link selectFile' onclick='AttachMent.addFile(this);'>选择</a>");
                    }
                    break;
                case 10:
                    el.attr("class", "ueditor");
                    break;
                // 复选框
                case FieldPool.CHECKBOX:
                    // 单选按钮
                case FieldPool.RADIO_INPUT:
                    break;
                // office 控件
                // officecontrol
                case FieldPool.OFFICE_CONTROL:
                    el.attr("type", "hidden");
                    el.attr("class", "hidden");
                    el.attr("controltype", "office");

                    String html = "<div id='div_" + controlName.replace(":", "_") + "'";
                    String style = el.attr("style");
                    if (StringUtil.isNotEmpty(style)) {
                        html += " style='" + style + "' ";
                    }
                    html += " class='office-div'></div>";
                    el.after(html);

                    break;
                // 日期类型
                case FieldPool.DATEPICKER:
                    el.wrap("<span></span>");
                    el.addClass("Wdate");
                    String format = "yyyy-MM-dd";
                    if (propertyMap.containsKey("format")) {
                        format = propertyMap.get("format");
                    }
                    if (propertyMap.containsKey("displayDate")) {
                        el.attr("displayDate", propertyMap.get("displayDate"));
                    }
                    el.attr("dateFmt", format);
                    break;
                // 隐藏域
                case FieldPool.HIDEDOMAIN:
                    el.wrap("<span></span>");
                    el.attr("type", "hidden");
                    break;
                // websigncontrol WEB印章控件
                case FieldPool.WEBSIGN_CONTROL:
                    el.attr("type", "hidden");
                    el.attr("class", "hidden");
                    el.attr("controltype", "webSign");

                    html = "<div id='div_" + controlName.replace(":", "_") + "'";
                    style = el.attr("style");
                    if (StringUtil.isNotEmpty(style)) {
                        html += " style='" + style + "' ";
                    }
                    html += " class='webSign-div'></div>";
                    el.after(html);
                    break;
                // pictureshowcontrol 图片展示控件
                case FieldPool.PICTURE_SHOW_CONTROL:
                    el.attr("type", "hidden");
                    el.attr("class", "hidden");
                    el.attr("controltype", "pictureShow");
                    html = "<div id='div_" + controlName.replace(":", "_") + "'  class='pictureShow-div' ";
                    style = el.attr("style");
                    if (StringUtil.isNotEmpty(style)) {
                        html += " style='" + style + "' ";
                    }
                    html += " >  ";
                    html += " <div id='div_" + controlName.replace(":", "_") + "_container' ></div>  ";
                    html += "   <table id='pictureShow_" + controlName + "_Toolbar'>";
                    html += "     <tr>";
                    html += "       <td width='80'>";
                    html += " 	       <a href='javascript:;' field='" + controlName + "' class='link selectFile' onclick='{PictureShowPlugin.upLoadPictureFile(this);}' >上传图片</a> ";
                    html += "       </td>";
                    html += "       <td width='80'>";
                    html += " 	       <a href='javascript:;' field='" + controlName + "' class='link del' onclick='{PictureShowPlugin.deletePictureFile(this);}' >删除图片</a> ";
                    html += "       </td>";
                    html += "     </tr>";
                    html += "   <table>";
                    html += " </div>  ";
                    el.removeAttr("style");
                    el.before(html);
                    break;
                case FieldPool.SELECTOR_PROCESS_INSTANCE:
                    el.wrap("<span></span>");
                    Element elProcessInstance = doc.createElement("input").attr("name", controlName + "ID").attr("type", "hidden").attr("class", "hidden");
                    Pair pairProcessInstance = new Pair(elProcessInstance, formField.getFieldName() + "ID");
                    list.add(pairProcessInstance);
                    el.before(elProcessInstance);
                    el.attr("readonly", "readonly");
                    break;
                default:
                    el.wrap("<span></span>");
                    break;
            }
        }
        return list;

    }

    /**
     * 移除外围span对象。
     *
     * <pre>
     * &lt;span style="display:inline-block" name="editable-input"><input type="text" external="" />&lt;/span>
     * 此方法删除外围name为editable-input的span对象。
     * </pre>
     */
    private static void removeWrap(Element parentEl) {

        for (Iterator<Element> it = parentEl.children().iterator(); it.hasNext(); ) {
            Node elClone = it.next();
            parentEl.before(elClone);
        }
        parentEl.remove();

    }

    /**
     * 处理主表字段的权限计算和对控件赋值。
     *
     * @param el        el
     * @param fieldName fieldName
     */
    private static String parseMainField(Element el, String fieldName) {
        String controltype = el.attr("controltype");
        // 控件类型
        String type = el.attr("type").toLowerCase();
        // 附件的处理方式
        if ("attachment".equalsIgnoreCase(controltype)) {
            Element parent = getContainer(el, "div_attachment_container");
            parent.attr("right", "${service.getFieldRight('" + fieldName + "',  permission)}");
            el.val("${service.getFieldValue('" + fieldName + "',model)}");
        }

        // pictureShow控件的处理
        // 设置pictureShow的值和权限。
        else if ("pictureShow".equalsIgnoreCase(controltype)) {
            el.attr("value", "${service.getFieldValue('" + fieldName + "',model,'" + controltype + "')}");
            // 设置权限。
            el.attr("right", "${service.getFieldRight('" + fieldName + "',  permission)}");
        }
        else if ("uploadFileList".equalsIgnoreCase(el.attr("class"))||"uploadImgList".equalsIgnoreCase(el.attr("class"))) {
            Element elParent = el.parent();
            elParent.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getFileImage('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }
        //选择器按钮
        else if ("layui-input selectorInput".equalsIgnoreCase(el.attr("class"))) {
            Element elParent = el.parent().parent();
            elParent.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSelector('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }
       else if ("layui-input-block radioOptionCont".equalsIgnoreCase(el.attr("class"))||"layui-input-block checkOptionCont".equalsIgnoreCase(el.attr("class"))) {
            el.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getCheckRadio('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            el.before(str);
            el.remove();
        }
        // webSign控件的处理
        // 设置webSign的值和权限。
        else if ("webSign".equalsIgnoreCase(controltype)) {
            el.attr("value", "${service.getFieldValue('" + fieldName + "',model)}");
            // 设置权限。
            el.attr("right", "${service.getFieldRight('" + fieldName + "',  permission)}");
        }
        // office控件的处理
        // 设置office的值和权限。
        else if ("office".equalsIgnoreCase(controltype)) {
            el.attr("value", "${service.getFieldValue('" + fieldName + "',model)}");
            // 设置权限。
            el.attr("right", "${service.getFieldRight('" + fieldName + "',  permission)}");
            // 设置工具栏目权限
            el.attr("menuRight", "${service.getFieldMenuRight('" + fieldName + "',  permission)}");
        }

        else if ("checkbox".equalsIgnoreCase(type) || "radio".equalsIgnoreCase(type)) {
            String value = el.attr("value");
            // 给checkbox设置是否chk和disabled属性。
            // 用户在模版中取值。
            el.attr("chk", "1").attr("disabled", "disabled");
            Element elParent = el.parent();
            String parentNodeName = elParent.nodeName();
            if (!"label".equals(parentNodeName)) {
                return fieldName + "的html代码必须为<label><input type='checkbox|radio' value='是'/>是</label>的形式";
            }
            // 将html赋值给一个变量，在使用service.getRdoChkBox 方法做解析
            // 如果外层元素是label，就把<#assign fieldName><label><input type='checkbox' value='' /></label></#assign>当成一个整体进行处理。
            String tmp = "label".equals(parentNodeName) ? elParent.toString() : el.toString();

            String str = "<span>&lt;#assign " + fieldName + "Html&gt;" + tmp + " &lt;/#assign&gt;" + "\r\n${service.getRdoChkBox('" + fieldName + "', " + fieldName + "Html,'" + value + "', model, permission)}</span>";
            elParent.before(str);
            elParent.remove();
        }
        // 多行文本
        else if ("textarea".equalsIgnoreCase(el.nodeName())) {
            el.append("#value");
            String str = "<span>&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getField('" + fieldName + "'," + fieldName + "Html, model, permission)}</span>";
            el.before(str);
            el.remove();
        }
        //数据字典 那些树的select  tree
        else if ("hidden".equalsIgnoreCase(type)) {
            //el.attr("value", "#value");
            Element elParent = el.parent().parent().parent();
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getHiddenField('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }

        // 处理文本输入框
        else if ("input".equalsIgnoreCase(el.nodeName())) {
            el.attr("value", "#value");
            // 处理选择器的的情况
            String ctlType = el.attr("ctlType").toLowerCase();
            if ("selector".equalsIgnoreCase(ctlType)) {
                el.attr("initvalue", "${service.getFieldValue('" + fieldName + "id', model)}");
            }
            String str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getField('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            // 隐藏的文本框在只读权限下面不返回value
            if ("hidden".equalsIgnoreCase(type)) {
                str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getHiddenField('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            }
            el.before(str);
            el.remove();
        }
        // 下拉框
        else if ("select".equalsIgnoreCase(el.nodeName())) {

            Element elParent = el.parent();
            el.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSelect('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }
        // 处理选择器的a标签
        else if ("a".equalsIgnoreCase(el.nodeName())) {
            String str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getLink('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            el.before(str);
            el.remove();
        }
        return "";
    }

    /**
     * 生成字段。
     *
     * <pre>
     * 对字段的external属性进行解析。
     *
     * external 为一个json对象。
     *
     * 存储字段类型，备注，值来源，时间格式，选项，条件等信息。
     * </pre>
     */
    private static FormField parseExternal(Element el, ParseReult result) {

        FormField formField = new FormField();

        String external = el.attr("external").replace("&#39;", "\"").replace("&quot;", "\"");
        List<Node> childNodes = el.childNodes();
        String defValue = "";
        for (Node node : childNodes) {
            defValue = node.attr("value");
        }
        formField.setDefValue(defValue);
        // 移除external属性。
        el.removeAttr("external");
        JSONObject jsonObject = null;
        try {
            jsonObject = JSONObject.fromObject(external);
        } catch (Exception ex) {
            result.addError(external + "错误的JSON格式!");
            return null;
        }

        // 获取字段名
        String fieldName = jsonObject.getString("name");

        if (StringUtil.isEmpty(fieldName)) {
            result.addError(external + "没有定义字段名");
            return null;
        }

        formField.setFieldName(fieldName);

        // 字段类型
        JSONObject dbType = (JSONObject) jsonObject.get("dbType");

        if (dbType == null) {
            result.addError(fieldName + ",没有定义字段类型。");
            return null;
        }
        // 处理字段类型。
        handFieldType(dbType, formField, result);
        // 注释
        String comment = (String) jsonObject.get("comment");
        formField.setFieldDesc((comment == null) ? fieldName : comment);
        // 验证规则
        // String validRule=(String)jsonObject.get("validRule");
        // formField.setValidRule(validRule==null?"":validRule);
        handStyle(jsonObject, formField);
        // dictType,字典类型
        handDictType(jsonObject, formField);
        // 值来源处理
        handValueFrom(jsonObject, formField);
        // 处理选项。
        handOption(jsonObject, formField);
        // 处理条件
        // handCondition(jsonObject,formField);
        // 获取控件类型。
        short controlType = handControlType(el, jsonObject);

        formField.setControlType(controlType);

        handOptions(jsonObject, formField);

        handFormUser(jsonObject, formField);

        // 人员选择器显示当前用户
        handShowCurUser(jsonObject, formField);

        // 组织选择器显示当前组织
        handShowCurOrg(jsonObject, formField);

        //处理人员，组织，岗位选择器的限定范围
        handOrgUserScope(jsonObject, formField);

        // 附件直接文件上传
        handAttachMent(jsonObject, formField);

        // 处理千分位和货币问题
        handComdifyAndCoin(jsonObject, formField);

        return formField;
    }

    /**
     * 处理人员，组织，岗位选择器的限定范围
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handOrgUserScope(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == FieldPool.SELECTOR_ORG_SINGLE || formField.getControlType() == FieldPool.SELECTOR_ORG_MULTI ||
                formField.getControlType() == FieldPool.SELECTOR_USER_MULTI || formField.getControlType() == FieldPool.SELECTOR_USER_SINGLE ||
                formField.getControlType() == FieldPool.SELECTOR_POSITION_MULTI || formField.getControlType() == FieldPool.SELECTOR_POSITION_SINGLE) {
            JSONObject jsonObj = null;
            String ctlProperty = formField.getCtlProperty();
            if (StringUtil.isNotEmpty(ctlProperty)) {
                jsonObj = JSONObject.fromObject(ctlProperty);
            } else {
                jsonObj = JSONObject.fromObject("{}");
            }
            Object scope = jsonObject.get("scope");
            if (BeanUtils.isNotEmpty(scope)) {
                jsonObj.element("scope", scope);
            }
            formField.setCtlProperty(jsonObj.toString());
        }
    }


    /**
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handComdifyAndCoin(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == 1) {
            JSONObject dbType = (JSONObject) jsonObject.get("dbType");
            String ctlProperty = formField.getCtlProperty();
            JSONObject jsonObj = null;
            if (StringUtil.isNotEmpty(ctlProperty)) {
                jsonObj = JSONObject.fromObject(ctlProperty);
            } else {
                jsonObj = JSONObject.fromObject("{}");
            }
            if (dbType.containsKey("isShowComdify")) {
                Short isShowComdify = 0;
                // 为了兼容旧版本数据
                FormUtil.isInteger(dbType,isShowComdify);
                jsonObj.element("isShowComdify", isShowComdify);
            }
            if (dbType.containsKey("coinValue")) {
                String coinValue = dbType.getString("coinValue");
                jsonObj.element("coinValue", coinValue);
            }
            if (dbType.containsKey("decimalLen")) {
                String decimalValue = dbType.getString("decimalLen");
                jsonObj.element("decimalValue", decimalValue);
            }
            if (dbType.containsKey("minValue")) {
                try {
                    int minValue = dbType.getInt("minValue");
                    int maxValue = dbType.getInt("maxValue");
                    if (minValue < maxValue) {
                        jsonObj.element("minValue", minValue);
                        jsonObj.element("maxValue", maxValue);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            formField.setCtlProperty(jsonObj.toString());
        }

    }

    /**
     * 保存options。
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handOptions(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == 11 || formField.getControlType() == 13 || formField.getControlType() == 14) {
            Object objOptions = jsonObject.get("options");
            if (objOptions == null) {
                return;
            }
            String options = objOptions.toString();
            formField.setOptions(options);
        }
    }

    /**
     * 保存是否作为表单用户
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handFormUser(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == 4 || formField.getControlType() == 6 || formField.getControlType() == 8) {
            Object isformuser = jsonObject.get("isformuser");
            if (isformuser == null) {
                return;
            }
            String ctlProperty = formField.getCtlProperty();
            JSONObject jsonObj = null;
            if (StringUtil.isNotEmpty(ctlProperty)) {
                jsonObj = JSONObject.fromObject(ctlProperty);
            } else {
                jsonObj = JSONObject.fromObject("{}");
            }
            jsonObj.element("isformuser", isformuser);
            formField.setCtlProperty(jsonObj.toString());
        }
    }

    /**
     * 保存人员选择器是否显示当前用户
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handShowCurUser(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == FieldPool.SELECTOR_USER_SINGLE) {
            Object showCurUser = jsonObject.get("showCurUser");
            if (showCurUser == null) {
                return;
            }
            String ctlProperty = formField.getCtlProperty();
            JSONObject jsonObj = null;
            if (StringUtil.isNotEmpty(ctlProperty)) {
                jsonObj = JSONObject.fromObject(ctlProperty);
            } else {
                jsonObj = JSONObject.fromObject("{}");
            }
            jsonObj.element("showCurUser", showCurUser);
            formField.setCtlProperty(jsonObj.toString());
        }
    }

    /**
     * 保存组织选择器是否显示当前组织
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handShowCurOrg(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == 18) {
            Object showCurOrg = jsonObject.get("showCurOrg");
            if (showCurOrg == null) {
                return;
            }
            String ctlProperty = formField.getCtlProperty();
            JSONObject jsonObj = null;
            if (StringUtil.isNotEmpty(ctlProperty)) {
                jsonObj = JSONObject.fromObject(ctlProperty);
            } else {
                jsonObj = JSONObject.fromObject("{}");
            }
            jsonObj.element("showCurOrg", showCurOrg);
            formField.setCtlProperty(jsonObj.toString());
        }
    }

    /**
     * 保存附件是否直接上传
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handAttachMent(JSONObject jsonObject, FormField formField) {
        if (formField.getControlType() == 9) {
            Object directUpLoad = jsonObject.get("directUpLoad");
            if (directUpLoad == null) {
                return;
            }
            String ctlProperty = formField.getCtlProperty();
            JSONObject jsonObj = null;
            if (StringUtil.isNotEmpty(ctlProperty)) {
                jsonObj = JSONObject.fromObject(ctlProperty);
            } else {
                jsonObj = JSONObject.fromObject("{}");
            }
            jsonObj.element("directUpLoad", directUpLoad);
            formField.setCtlProperty(jsonObj.toString());
        }
    }

    /**
     * 获取控件类型
     *
     * @param el         el
     * @param jsonObject jsonObject
     * @return short
     */
    private static short handControlType(Element el, JSONObject jsonObject) {
        String clsName = el.attr("class").toLowerCase();
        Short controlType = controlTypeMap.get("textinput");
        if ("personpicker".equals(clsName)) {
            if (jsonObject.containsKey("singleselect")) {
                if ("1".equals(jsonObject.get("singleselect").toString())) {
                    controlType = controlTypeMap.get("user");
                } else {
                    controlType = controlTypeMap.get("userMulti");
                }
            } else {
                controlType = controlTypeMap.get("user");
            }
        } else if ("rolepicker".equals(clsName)) {
            if (jsonObject.containsKey("singleselect")) {
                if ("1".equals(jsonObject.get("singleselect").toString())) {
                    controlType = controlTypeMap.get("rolepicker");
                } else {
                    controlType = controlTypeMap.get("rolepickerMulti");
                }
            } else {
                controlType = controlTypeMap.get("rolepicker");
            }

        } else if ("departmentpicker".equals(clsName)) {
            if (jsonObject.containsKey("singleselect")) {
                if ("1".equals(jsonObject.get("singleselect").toString())) {
                    controlType = controlTypeMap.get("departmentpicker");
                } else {
                    controlType = controlTypeMap.get("departmentpickerMulti");
                }
            } else {
                controlType = controlTypeMap.get("departmentpicker");
            }
        } else if ("positionpicker".equals(clsName)) {
            if (jsonObject.containsKey("singleselect")) {
                if ("1".equals(jsonObject.get("singleselect").toString())) {
                    controlType = controlTypeMap.get("positionpicker");
                } else {
                    controlType = controlTypeMap.get("positionpickerMulti");
                }
            } else {
                controlType = controlTypeMap.get("positionpicker");
            }
        } else {
            if (controlTypeMap.containsKey(clsName)) {
                controlType = controlTypeMap.get(clsName);
            }
        }
        return controlType;
    }

    /**
     * 设置验证规则。
     *
     * @param formField formField
     * @return String
     */
    private static String handValidate(FormField formField) {
        // 处理验证规则
        JSONObject valid = JSONObject.fromObject("{}");

        if (formField.getIsRequired() == 1) {
            valid.put("required", true);
        }
        // 验证规则。
        if (StringUtil.isNotEmpty(formField.getValidRule())) {
            valid.put(formField.getValidRule(), true);
        }
        //
        String fieldType = formField.getFieldType();

        if (FormConstants.STR_VARCHAR.equals(fieldType)) {
            valid.put(FormConstants.STR_MAX_LENGTH, formField.getCharLen());
        } else if (FormConstants.STR_DATE.equals(fieldType)) {
            valid.put(FormConstants.STR_DATE, true);
        } else if (FormConstants.STR_NUMBER.equals(fieldType)) {
            valid.put(FormConstants.STR_NUMBER, true);
            valid.put(FormConstants.STR_MAX_INT_LEN, formField.getIntLen());
            valid.put(FormConstants.STR_MAX_DECIMAL_LEN, formField.getDecimalLen());
            String ctlExt = formField.getCtlProperty();
            if (StringUtil.isNotEmpty(ctlExt)) {
                JSONObject jsonObject = JSONObject.fromObject(ctlExt);
                if (jsonObject.containsKey(FormConstants.STR_MIN_VALUE)) {
                    String minValue = jsonObject.getString(FormConstants.STR_MIN_VALUE);
                    String maxValue = jsonObject.getString(FormConstants.STR_MAX_VALUE);
                    valid.put(FormConstants.STR_RANGE, "[" + minValue + "," + maxValue + "]");
                }
            }
        }

        return valid.toString();
    }

    /**
     * 解析数据字典。
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handDictType(JSONObject jsonObject, FormField formField) {
        String dictType = (String) jsonObject.get("dictType");
        if (StringUtil.isEmpty(dictType)) {
            return;
        }
        formField.setDictType(dictType);

    }

    /**
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handStyle(JSONObject jsonObject, FormField formField) {
        StringBuffer style = new StringBuffer();
        Object objWidthOptions = jsonObject.get("width");
        Object objHeightOptions = jsonObject.get("height");
        Object objWidthUnit = jsonObject.get("widthUnit");
        Object objHeightUnit = jsonObject.get("heightUnit");
        if (BeanUtils.isEmpty(objWidthUnit)) {
            objWidthUnit = "px";
        }
        if (BeanUtils.isEmpty(objHeightUnit)) {
            objHeightUnit = "px";
        }
        if (BeanUtils.isNotEmpty(objWidthOptions)) {
            style.append("width:" + objWidthOptions + objWidthUnit + ";");
        }
        if (BeanUtils.isNotEmpty(objHeightOptions)) {
            style.append("height:" + objHeightOptions + objHeightUnit + ";");
        }
        formField.setStyle(style.toString());

    }

    /**
     * 处理值来源
     *
     * <pre>
     * 0,表单输入。
     * 1.脚本运算(显示)。
     * 2.脚本运算(不显示)。
     * 3.流水号。
     * </pre>
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handValueFrom(JSONObject jsonObject, FormField formField) {
        JSONObject valueFrom = (JSONObject) jsonObject.get("valueFrom");
        if (valueFrom == null) {
            return;
        }
        Short value = Short.parseShort(valueFrom.get("value").toString());
        formField.setValueFrom(value);
        switch (value) {
            // 表单输入
            case 0:
                // 当值来源是表单输入的时候，content：为验证规则。
                if (valueFrom.containsKey("content")) {
                    String validRule = valueFrom.getString("content");
                    if (StringUtil.isNotEmpty(validRule)) {
                        formField.setValidRule(validRule);
                    }
                }
                break;
            // 脚本
            case 1:
            case 2:
                String content = valueFrom.getString("content");
                formField.setScript(content);
                Object scriptID = valueFrom.get("scriptID");
                formField.setScriptID(scriptID == null ? "" : scriptID.toString());
                break;
            // 流水号。
            case 3:
                String identity = valueFrom.getString("content");
                formField.setIdentity(identity);
                // 处理流水号中是否勾选了 是否显示在流程启动页面中
                JSONObject jsonObj = null;
                String ctlProperty = formField.getCtlProperty();
                if (StringUtil.isNotEmpty(ctlProperty)) {
                    jsonObj = JSONObject.fromObject(ctlProperty);
                } else {
                    jsonObj = JSONObject.fromObject("{}");
                }

                if (jsonObject.containsKey("isShowidentity")) {
                    String isShowidentity = jsonObject.getString("isShowidentity");
                    jsonObj.put("isShowidentity", isShowidentity);
                } else {
                    jsonObj.put("isShowidentity", "0");
                }
                formField.setCtlProperty(jsonObj.toString());
                break;
            default:
        }

    }

    /**
     * 处理必填，是否列表，是否查询条件，是否流程变量。
     *
     * @param jsonObject jsonObject
     * @param formField  formField
     */
    private static void handOption(JSONObject jsonObject, FormField formField) {
        Object isRequired = (Object) jsonObject.get("isRequired");
        if (isRequired == null) {
            formField.setIsRequired((short) 0);
        } else {
            formField.setIsRequired(Short.parseShort(isRequired.toString()));
        }
        // 列表
        Object isList = (Object) jsonObject.get("isList");
        if (isList == null) {
            formField.setIsList((short) 0);
        } else {
            formField.setIsList(Short.parseShort(isList.toString()));
        }
        // 查询条件。
        Object isQuery = jsonObject.get("isQuery");
        if (isQuery == null) {
            formField.setIsQuery((short) 0);
        } else {
            formField.setIsQuery(Short.parseShort(isQuery.toString()));
        }
        // 流程变量
        Object isFlowVar = jsonObject.get("isFlowVar");
        if (isFlowVar == null) {
            formField.setIsFlowVar((short) 0);
        } else {
            formField.setIsFlowVar(Short.parseShort(isFlowVar.toString()));
        }
        Object isAllowMobile = jsonObject.get("isAllowMobile");
        if (isAllowMobile == null) {
            formField.setIsAllowMobile((short) 0);
        } else {
            formField.setIsAllowMobile(Short.parseShort(isAllowMobile.toString()));
        }

        // web印章验证
        Object isWebSign =  jsonObject.get("isWebSign");
        if (isWebSign == null) {
            formField.setIsWebSign((short) 0);
        } else {
            formField.setIsWebSign(Short.parseShort(isWebSign.toString()));
        }

        // 处理文字类型日期格式
        Object isDateString = jsonObject.get("isDateString");
        if ("varchar".equals(formField.getFieldType()) && isDateString != null) {
            formField.setIsDateString(Short.parseShort(isDateString.toString()));
            String displayDate = formField.getPropertyMap().get("displayDate");
            if (displayDate != null) {
                formField.setIsCurrentDateStr(Short.parseShort(displayDate));
            }
        }

        // 处理超连接
        Object isReference = jsonObject.get("isReference");
        if (isReference == null) {
            formField.setIsReference((short) 0);
        } else {
            formField.setIsReference(Short.parseShort(isReference.toString()));
        }
    }

    /**
     * 处理字段类型。
     *
     * @param dbType    {type:'varchar',length:20,}
     * @param formField formField
     */
    private static void handFieldType(JSONObject dbType, FormField formField, ParseReult result) {
        if (!dbType.containsKey("type")) {
            result.addError("字段:" + formField.getFieldName() + "," + formField.getFieldDesc() + ",没有设置数据类型!");
            return;
        }
        // type
        String type = dbType.getString("type");
        if (StringUtil.isEmpty(type)) {
            result.addError("字段:" + formField.getFieldName() + "," + formField.getFieldDesc() + ",没有设置数据类型!");
            return;
        }
        if (!isValidType(type)) {
            result.addError("字段:" + formField.getFieldName() + "," + formField.getFieldDesc() + ",数据类型设置错误:" + type);
            return;
        }

        formField.setCharLen(0);
        formField.setIntLen(0);
        formField.setDecimalLen(0);

        formField.setFieldType(type);
        if ("varchar".equals(type)) {
            if (!dbType.containsKey("length")) {
                result.addError("字段:" + formField.getFieldName() + "," + formField.getFieldDesc() + ",数据类型(VARCHAR)长度未设置。");
                return;
            }

            // length
            int len = dbType.getInt("length");

            formField.setCharLen(len);
            // 设置日期格式
            setDateFormat(dbType, formField);
        } else if ("number".equals(type)) {
            if (!dbType.containsKey("intLen")) {
                result.addError("字段:" + formField.getFieldName() + "," + formField.getFieldDesc() + ",数据类型(number)数据长度未设置。");
                return;
            }
            int intLen = dbType.getInt("intLen");
            int decimalLen = 0;
            Short isShowComdify = 0;
            String coinValue = "";
            // decimalLen
            if (dbType.containsKey("decimalLen")) {
                decimalLen = dbType.getInt("decimalLen");
            }
            if (dbType.containsKey("isShowComdify")) {
                // 为了兼容旧版本数据
                FormUtil.isInteger(dbType,isShowComdify);
            }
            if (dbType.containsKey("coinValue")) {
                coinValue = dbType.getString("coinValue");
            }
            formField.setCoinValue(coinValue);
            formField.setIsShowComdify(isShowComdify);
            formField.setIntLen(intLen);
            formField.setDecimalLen(decimalLen);
        } else if ("date".equals(type)) {
            setDateFormat(dbType, formField);

        }
    }

    /**
     * 校验字段类型是否Integer。
     *
     * @param dbType 字段类型
     */
    private static void isInteger(JSONObject dbType,Short isShowComdify) {
        String temp = dbType.getString("isShowComdify");
        boolean isInteger = temp.matches("^[0-9]*$");
        if (isInteger) {
            isShowComdify = Short.parseShort(temp);
        } else {
            if ("true".equals(temp)) {
                isShowComdify = (short) 1;
            } else if ("false".equals(temp)) {
                isShowComdify = (short) 0;
            }
        }
    }

    /**
     * 校验字段类型是否有效。
     *
     * @param type type
     * @return boolean
     */
    private static boolean isValidType(String type) {
        if ("varchar".equals(type) || "number".equals(type) || "date".equals(type) || "clob".equals(type)) {
            return true;
        }
        return false;
    }

    /**
     * 时间格式的处理。
     *
     * @param dbType    dbType
     * @param formField formField
     */
    private static void setDateFormat(JSONObject dbType, FormField formField) {
        String ctlProperty = formField.getCtlProperty();
        JSONObject jsonObj = null;
        if (StringUtil.isNotEmpty(ctlProperty)) {
            jsonObj = JSONObject.fromObject(ctlProperty);
        } else {
            jsonObj = JSONObject.fromObject("{}");
        }
        // 格式
        String format = (String) dbType.get("format");
        String dateStrFormat = (String) dbType.get("dateStrFormat");
        if (format == null && dateStrFormat == null) {
            jsonObj.element("format", "yyyy-MM-dd");
        } else if (format != null) {
            jsonObj.element("format", format);
        } else if (dateStrFormat != null) {
            jsonObj.element("format", dateStrFormat);
        }
        // 显示时间
        Object displayDate = dbType.get("displayDate");
        if (displayDate == null) {
            jsonObj.element("displayDate", 0);
        } else {
            jsonObj.element("displayDate", Integer.parseInt(displayDate.toString()));
        }
        formField.setCtlProperty(jsonObj.toString());
    }

    public static String getPrintFreeMarkerTemplate(String html, String tableName, String comment) {
        Document doc = Jsoup.parseBodyFragment(html);
        // 获取主表中有external属性的控件集合。
        Elements mainFields = doc.select("[external]");

        // 处理流水号
        parseSerialNumber(doc);
        // 处理国际化资源
        // parseI18nKey(doc);
        // 处理表单中的其他国际化资源
        // parseFormI18n(doc);
        if (mainFields.size() > 0) {// 由编辑器生成的表单
            ParseReult result = new ParseReult();
            parsePrintSubTableOfFormEditor(doc, result);
            parsePrintMainTableOfFormEditor(doc, tableName, comment, result);
        }
        // 遍历主表字段
        parsePrintMainField(doc);
        // 处理子表。
        parsePrintSubTable(doc);
        // 解析意见
        parsePrintOpinion(doc);
        String rtn = doc.body().html();
        rtn = rtn.replaceAll("&lt;", "<").replaceAll("&gt;", ">");
        rtn = "<#setting number_format=\"#\">\n" + rtn;
        return rtn;
    }

    /**
     * 处理流水号
     *
     * @param doc doc
     */
    private static void parseSerialNumber(Document doc) {
        Elements list = doc.select("span[serialnum=true]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String defaultVal = el.text();
            String str = "<#if model.others.serialnum??>${model.others.serialnum}<#else>" + defaultVal + "</#if>";
            el.text(str);
        }
    }

    private static void parsePrintMainField(Document doc) {
        Elements list = doc.select("input[name^=m:],textarea[name^=m:],select[name^=m:],a.link");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            // 获取字段名
            String fieldName = name.replaceAll("^.*:", "").toLowerCase();
            // 解析模版，对模版进行复制复制和授权的处理。
            parsePrintMainField(el, fieldName);
        }
    }

    private static void parsePrintMainField(Element el, String fieldName) {
        String controltype = el.attr("controltype");
        // 控件类型
        String type = el.attr("type").toLowerCase();
        // 附件的处理方式
        if ("attachment".equalsIgnoreCase(controltype)) {
            // 在<div name="div_attachment_container"></div>中加一个right="r"的属性
            Element parent = getContainer(el, "div_attachment_container");
            parent.attr("right", "r");
            el.val("${service.getFieldValue('" + fieldName + "',model)}");
        }

        // pictureShow控件的处理
        // 设置pictureShow的值和权限。
        else if ("pictureShow".equalsIgnoreCase(controltype)) {
            el.attr("value", "${service.getFieldValue('" + fieldName + "',model,'" + controltype + "')}");
        }
        // webSign控件的处理
        // 设置webSign的值和权限。
        else if ("webSign".equalsIgnoreCase(controltype)) {
            el.attr("value", "${service.getFieldValue('" + fieldName + "',model)}");
        }
        // office控件的处理
        // 设置office的值和权限。
        else if ("office".equalsIgnoreCase(controltype)) {
            el.attr("value", "${service.getFieldValue('" + fieldName + "',model)}");
        }
        // checkbox和radio的处理
        // checkbox和radio的必须为以下格式
        else if ("checkbox".equalsIgnoreCase(type) || "radio".equalsIgnoreCase(type)) {
            String value = el.attr("value");
            el.attr("chk", "1").attr("disabled", "disabled");
            Element elParent = el.parent();
            String parentNodeName = elParent.nodeName();
            String tmp = "label".equals(parentNodeName) ? elParent.toString() : el.toString();
            // 将html赋值给一个变量，在使用service.getRdoChkBox 方法做解析
            String str = "<span>&lt;#assign " + fieldName + "Html&gt;" + tmp + " &lt;/#assign&gt;" + "\r\n${service.getPrintRdoChkBox('" + fieldName + "', " + fieldName + "Html,'" + value + "', model)}</span>";
            elParent.before(str);
            elParent.remove();
        }
        // 多行文本
        else if ("textarea".equalsIgnoreCase(el.nodeName())) {
            String str = "${model.main." + fieldName + "}";
            el.before(str);
            el.remove();
        }
        // 处理文本输入框
        else if ("input".equalsIgnoreCase(el.nodeName())) {
            if (!"hidden".equals(type)) {
                el.before("${model.main." + fieldName + "}");
            }
            el.remove();
        }
        // 下拉框
        else if ("select".equalsIgnoreCase(el.nodeName())) {
            // 防止有'时HTML会出现乱嵌套 "'" 报错 所以要把 ' 改成 \';
            String tmp = el.toString().replaceAll("&quot;", "'").replaceAll("'", "\\\\'");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + tmp + " &lt;/#assign&gt;" + "\r\n${service.getPrintOptionValue('" + fieldName + "', " + fieldName + "Html, model)}";
            el.before(str);
            el.remove();
        }
        // 处理选择器的a标签
        else if ("a".equalsIgnoreCase(el.nodeName())) {
            el.remove();
        }

    }

    private static void parsePrintSubTable(Document doc) {
        Elements list = doc.select("div[type=subtable]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element subTable = it.next();
            String tableName = subTable.attr("tableName").toLowerCase();
            if (StringUtil.isEmpty(tableName)) {
                logger.debug("subtable tableName is not specialed");
                continue;
            }

            // 查询编辑行
            Elements rows = subTable.select("[formtype=edit],[formtype=form]");
            if (rows.size() == 0) {
                logger.debug("no formtype row defined");
                return;
            }
            Element row = rows.get(0);
            String mode = row.attr("formtype");
            Element newRow = row.clone().attr("formtype", "newrow");
            // Map<String,Boolean> checkboxTagMap = new HashMap<String, Boolean>();
            if (FormDef.EDIT_INLINE.equals(mode)) {
                Elements fields = newRow.select("[name^=s:]");
                for (Iterator<Element> its = fields.iterator(); its.hasNext(); ) {
                    Element el = its.next();
                    String name = el.attr("name");
                    String type = el.attr("type");
                    String controltype = el.attr("controltype");
                    // 获取字段名
                    String fieldName = name.replaceAll("^.*:", "").toLowerCase();
                    // 复选框和radio
                    if ("checkbox".equals(type) || "radio".equals(type)) {
                        el.attr("chk", "1").attr("disabled", "disabled");
                        String value = el.attr("value");
                        // 防止有'时HTML会出现乱嵌套 "'" 报错 所以要把 ' 改成 \';
                        String html = el.toString().replaceAll("&quot;", "'").replaceAll("'", "\\\\'");
                        el.before("${service.getRdoChkBox('" + fieldName + "', '" + html + "','" + value + "', table)}");
                        el.remove();
                        // 附件的处理方式
                    } else if ("attachment".equalsIgnoreCase(controltype)) {
                        // 在<div name="div_attachment_container"></div>中加一个right="r"的属性
                        Element parent = getContainer(el, "div_attachment_container");
                        parent.attr("right", "r");
                        el.val("${service.getSubTableAttachMent('" + fieldName + "', table)}");
                    }
                    // 下拉选项
                    else if ("select".equalsIgnoreCase(el.nodeName())) {
                        // 防止有'时HTML会出现乱嵌套 "'" 报错 所以要把 ' 改成 \';
                        String html = el.toString().replaceAll("&quot;", "'").replaceAll("'", "\\\\'");
                        el.before("${service.getSubTableOptionValue('" + fieldName + "', '" + html + "', table)}");
                        el.remove();
                    } else {
                        el.before("${table." + fieldName + "}");
                        el.remove();
                    }
                }

            } else {
                Elements windowRows = subTable.select("[formtype=window]");
                if (windowRows.size() != 1) {
                    logger.debug("window mode hasn't window defined");
                    return;
                }
                Element window = windowRows.get(0);
                parseSubTableFormField(doc, newRow, window);
                windowRows.remove();
            }
            row.after(newRow);
            newRow.before("&lt;#if model.sub." + tableName + " != null&gt; &lt;#list model.sub." + tableName + ".dataList as table&gt;");
            newRow.after("&lt;/#list> &lt;/#if&gt;");
            row.remove();
            subTable.removeAttr("right");
            subTable.attr("type", "sub");
        }

    }

    private static void parsePrintOpinion(Document doc) {
        // opinion:www
        Elements list = doc.select("[name^=opinion:]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            String opinionName = name.replaceFirst("^opinion:", "");
            String str = "&lt;#assign " + opinionName + "Opinion&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getOpinion('" + opinionName + "',model)}";
            el.before(str);
            el.remove();

        }
    }

    /**
     * 处理表字段的国际化资源
     *
     * @param doc
     */
    @SuppressWarnings("unused")
    private static void parseI18nKey(Document doc) {
        Elements list = doc.select("span[i18nkey]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String i18nkey = el.attr("i18nkey").replaceAll(":", "_");
            String defaultVal = el.text();
            String str = "&lt;#if i18nmap." + i18nkey + "??&gt;${i18nmap." + i18nkey + "}&lt;#else&gt;" + defaultVal + "&lt;/#if&gt;";
            el.before(str);
            el.remove();
        }
    }

    /**
     * 处理表单中其他资源的国际化
     *
     * @param doc doc
     */
    @SuppressWarnings("unused")
    private static void parseFormI18n(Document doc) {
        Elements list = doc.select("p[i18n]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String i18n = el.attr("i18n");
            JSONObject jobject = JSONObject.fromObject(i18n);
            String reskey = jobject.getString("reskey");
            String defaultVal = el.text();
            String str = "&lt;#if i18nformmap." + reskey + "??&gt;&lt;p&gt;${i18nformmap." + reskey + "}&lt;br/&gt;&lt;/p&gt;&lt;#else&gt;&lt;p&gt;" + defaultVal + "&lt;br/&gt;&lt;/p&gt;&lt;/#if&gt;";
            el.before(str);
            el.remove();
        }
    }

    /**
     * 生成编辑器设计的表单的主表模板
     *
     * @param doc       doc
     * @param tableName tableName
     * @param comment   comment
     * @param result    result
     */
    private static void parsePrintMainTableOfFormEditor(Document doc, String tableName, String
            comment, ParseReult result) {
        FormTable formTable = new FormTable();
        formTable.setTableName(tableName);
        formTable.setTableDesc(comment);
        formTable.setIsMain((short) 1);
        formTable.setGenByForm(1);
        // 获取主表中有external属性的控件集合。
        Elements mainFields = doc.select("[external]");

        if (mainFields.size() == 0) {
            result.addError("主表【" + tableName + "," + comment + "】还未定义任何字段");
            return;
        }

        for (Iterator<Element> it = mainFields.iterator(); it.hasNext(); ) {
            Element el = it.next();
            // 从html中解析出字段。
            FormField formField = parseExternal(el, result);

            if (formField == null) {
                continue;
            }

            String controlName = "m:" + tableName + ":" + formField.getFieldName();

            boolean rtn = formTable.addField(formField);

            if (!rtn) {
                String error = "表单中主表:【" + tableName + "】，字段:【" + formField.getFieldDesc() + "】重复";
                if (StringUtil.isEmpty(tableName)) {
                    error = "主表中，字段:【" + formField.getFieldDesc() + "】重复";
                }
                result.addError(error);
                continue;
            }
            // 整理html。
            parseChilds(doc, el, controlName, formField);
            // 删除包装。
            removeWrap(el);
        }
    }

    private static void parsePrintSubTableOfFormEditor(Document doc, ParseReult result) {
        Elements list = doc.select("div[type=subtable]");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element subTable = it.next();
            // 如果子表设置了external属性，则先删除external属性。
            if (subTable.hasAttr("external")) {
                subTable.removeAttr("external");
                subTable.removeClass("subtable");
            }

            FormTable table = new FormTable();
            // 设置子表。
            String tableName = subTable.attr("tablename").toLowerCase();
            if (StringUtil.isEmpty(tableName)) {
                result.addError("有子表对象没有设置表名。");
                continue;
            }
            String comment = subTable.attr("tabledesc");

            table.setTableName(tableName);
            table.setTableDesc(comment);
            table.setIsMain((short) 0);
            table.setGenByForm(1);

            // 设置子表权限。
            // subTable.attr("right", "${service.getSubTablePermission('"+tableName+"', permission)}");
            Elements rows = subTable.select("[formtype=edit],[formtype=form]");
            if (rows.size() == 0) {
                logger.debug("no formtype row defined");
                result.addError("子表【" + tableName + "】没有定义属性【formtype】。");
                continue;
            }
            Element row = rows.get(0);
            Elements fields = row.select("[external]");
            if (fields.size() == 0) {
                result.addError("子表【" + tableName + "," + table.getTableDesc() + "】尚未定义任何字段");
                return;
            }

            for (Iterator<Element> ite = fields.iterator(); ite.hasNext(); ) {
                Element el = ite.next();
                // 解析字段。
                FormField formField = parseExternal(el, result);

                boolean rtn = table.addField(formField);

                String fieldName = formField.getFieldName();

                if (!rtn) {
                    String error = "表单中子表:【" + tableName + "】，字段:【" + formField.getFieldDesc() + "】重复";
                    if (StringUtil.isEmpty(tableName)) {
                        error = "子表中，字段:【" + formField.getFieldDesc() + "】重复";
                    }
                    result.addError(error);
                    continue;
                }

                String controlName = "s:" + tableName + ":" + fieldName;
                parseChilds(doc, el, controlName, formField);
                // 删除父节点
                removeWrap(el);
            }
        }
    }

    /**
     * 取得外键值。
     *
     * @param keyType
     * @param alias
     * @return
     * @throws Exception
     */
    public static Object getKey(int keyType, String alias) throws Exception {
        KeyGenerator generator = null;
        switch (keyType) {
            // guid
            case 1:
                generator = new GuidGenerator();
                break;
            // 流水号
            case 2:
                generator = new IdentityGenerator();
                break;
            // 时间序列
            case 3:
                generator = new TimeGenerator();
                break;
            default:
                break;
        }
        if (generator == null) {
            return UUIDUtils.getUUIDFor32();
        }
        generator.setAlias(alias);
        return generator.nextId();
    }


    /**
     * 解析html表单数据
     *
     * @param html
     * @param tableId
     * @return
     */
    public static String getFreeMarkerTemplate(String html, String tableId) {
        FormTableService bpmFormTableService = AppUtil.getBean(FormTableService.class);

        FormTable bpmFormTable = bpmFormTableService.getOneById(tableId);

        Document doc = Jsoup.parseBodyFragment(html);
        // 遍历主表字段
        parseMainField(doc);
        // 处理子表。
        parseSubTable(doc, bpmFormTable.getTableId());
        // 解析意见
        parseOpinion(doc);

        String rtn = doc.body().html();

        rtn = rtn.replaceAll("&lt;", "<").replaceAll("&gt;", ">");
        rtn = "<#setting number_format=\"#\">\n" + rtn;

        return rtn;
    }

    /**
     * 解析子表
     *
     * @param doc         :doc
     * @param mainTableId :主表id void
     * @throws
     * @since 1.0.0
     */
    private static void parseSubTable(Document doc, String mainTableId) {
        FormTableService bpmFormTableService = AppUtil.getBean(FormTableService.class);
        Elements list = doc.select("table.subFormTable");
        if(list.size() == 0){
            return;
        }
        Elements listMode = doc.select("a.addFormTr");
        String modetype = listMode.get(0).attr("modetype");
        for (Iterator<Element> it = list.iterator(); it.hasNext();) {
            Element subTable = it.next();
            String tableName = subTable.attr("class").split(" ")[1];

            if (StringUtil.isEmpty(tableName)) {
                logger.debug("subtable tableName is not specialed");
                continue;
            }
            String pkField = "";
            // 获取所有子表
            List<FormTable> bpmFormTables = bpmFormTableService.getSubTableByMainTableId(mainTableId);
            for (FormTable bft : bpmFormTables) {
                // 当子表名字跟表单内容的表名相同时就赋值
                if (!bft.getTableName().equals(tableName)){
                    continue;
                }
                pkField = bft.getPkField();
                continue;
            }
            // 设置子表权限。
            subTable.attr("right", "${permission.table." + tableName + "}");
            Elements rows = subTable.select("tr.temSpace");
            /*Map<String, Object> map = handNewRow(subTable, pkField, doc);

            if (map == null){
                continue;
            }

            Element newRow = (Element) map.get("newRow");*/
            for (Iterator<Element> row = rows.iterator(); row.hasNext();) {
                // 行内编辑模式
                if (FormDef.EDIT_INLINE.equals(modetype)) {
                    parseSubTableField(row.next());
                }
                // 弹出窗口
                else if (FormDef.EDIT_FORM.equals(modetype)) {
                    /*Elements windowRows = subTable.select("[formtype=window]");
                    if (windowRows.size() != 1) {
                        logger.debug("window mode hasn't window defined");
                        return;
                    }
                    Element window = windowRows.get(0);*/
                    parseSubTableField(row.next());
                }
            }
        }
    }

    /**
     * 处理行内编辑情况。
     *
     * @param newRow newRow
     */
    private static void parseSubTableField(Element newRow) {
        Elements list = newRow.select("input[name^=s:],div[name^=s:],ul[name^=s:],textarea[name^=s:],select[name^=s:],button.selectorBtn,button.uploadFileBtn,button.uploadImgBtn,a.link,a.extend");
        for (Iterator<Element> it = list.iterator(); it.hasNext(); ) {
            Element el = it.next();
            String name = el.attr("name");
            // 获取字段名
            String fieldName = name.replaceAll("^.*:", "").toLowerCase();
            // 处理附件的bug
            if (StringUtil.isEmpty(name)) {
                name = el.attr("field");
                // 不是子表
                if (StringUtil.isNotEmpty(name) && name.matches("m:(\\w*):(\\w*)")) {
                    fieldName = name.replaceAll("^.*:", "").toLowerCase();
                }
            }
            // 解析模版，对模版进行复制复制和授权的处理。
            parseSubField(el, fieldName);
        }
    }

    /**
     * 处理主表字段的权限计算和对控件赋值。
     *
     * @param el        el
     * @param fieldName fieldName
     */
    private static String parseSubField(Element el, String fieldName) {
        String controltype = el.attr("controltype");
        // 控件类型
        String type = el.attr("type").toLowerCase();
        // 附件的处理方式
        if ("attachment".equalsIgnoreCase(controltype)) {
            Element parent = getContainer(el, "div_attachment_container");
            parent.attr("right", "${service.getFieldRight('" + fieldName + "',  permission)}");
            el.val("${service.getFieldValue('" + fieldName + "',model)}");
        }
        else if ("uploadFileList".equalsIgnoreCase(el.attr("class"))||"uploadImgList".equalsIgnoreCase(el.attr("class"))) {
            Element elParent = el.parent();
            elParent.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubFileImage('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }
        //选择器按钮
        else if ("layui-input selectorInput".equalsIgnoreCase(el.attr("class"))) {
            Element elParent = el.parent().parent();
            elParent.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubSelector('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }
        else if ("layui-input-block radioOptionCont".equalsIgnoreCase(el.attr("class"))||"layui-input-block checkOptionCont".equalsIgnoreCase(el.attr("class"))) {
            el.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubCheckRadio('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            el.before(str);
            el.remove();
        }
        else if ("checkbox".equalsIgnoreCase(type) || "radio".equalsIgnoreCase(type)) {
            String value = el.attr("value");
            // 给checkbox设置是否chk和disabled属性。
            // 用户在模版中取值。
            el.attr("chk", "1").attr("disabled", "disabled");
            Element elParent = el.parent();
            String parentNodeName = elParent.nodeName();
            if (!"label".equals(parentNodeName)) {
                return fieldName + "的html代码必须为<label><input type='checkbox|radio' value='是'/>是</label>的形式";
            }
            // 将html赋值给一个变量，在使用service.getRdoChkBox 方法做解析
            // 如果外层元素是label，就把<#assign fieldName><label><input type='checkbox' value='' /></label></#assign>当成一个整体进行处理。
            String tmp = "label".equals(parentNodeName) ? elParent.toString() : el.toString();

            String str = "<span>&lt;#assign " + fieldName + "Html&gt;" + tmp + " &lt;/#assign&gt;" + "\r\n${service.getRdoChkBox('" + fieldName + "', " + fieldName + "Html,'" + value + "', model, permission)}</span>";
            elParent.before(str);
            elParent.remove();
        }
        // 多行文本
        else if ("textarea".equalsIgnoreCase(el.nodeName())) {
            el.append("#value");
            String str = "<span>&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubField('" + fieldName + "'," + fieldName + "Html, model, permission)}</span>";
            el.before(str);
            el.remove();
        }
        //数据字典 那些树的select  tree
        else if ("hidden".equalsIgnoreCase(type)) {
            //el.attr("value", "#value");
            Element elParent = el.parent().parent().parent();
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubHiddenField('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }

        // 处理文本输入框
        else if ("input".equalsIgnoreCase(el.nodeName())) {
            el.attr("value", "#value");
            // 处理选择器的的情况
            String ctlType = el.attr("ctlType").toLowerCase();
            if ("selector".equalsIgnoreCase(ctlType)) {
                el.attr("initvalue", "${service.getFieldValue('" + fieldName + "id', model)}");
            }
            String str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubField('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            // 隐藏的文本框在只读权限下面不返回value
            if ("hidden".equalsIgnoreCase(type)) {
                str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubHiddenField('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            }
            el.before(str);
            el.remove();
        }
        // 下拉框
        else if ("select".equalsIgnoreCase(el.nodeName())) {

            Element elParent = el.parent();
            el.attr("val", "#value");
            String str = "&lt;#assign " + fieldName + "Html&gt;" + elParent.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubSelect('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            elParent.before(str);
            elParent.remove();
        }
        // 处理选择器的a标签
        else if ("a".equalsIgnoreCase(el.nodeName())) {
            String str = "&lt;#assign " + fieldName + "Html&gt;" + el.toString() + " &lt;/#assign&gt;" + "\r\n${service.getSubLink('" + fieldName + "'," + fieldName + "Html, model, permission)}";
            el.before(str);
            el.remove();
        }
        return "";
    }
}